import uuid
from datetime import datetime, timedelta


class Condition(object):

    def __init__(self, name, typ, value, machine=None):
        self.name = name if bool(name) else str(uuid.uuid1())
        self.value = value
        assert typ in ['int', 'float', 'duration', 'string', 'bool'], \
            f'typ parameter must be one of int/float/string/duration/bool, not {typ}'
        self.type = typ
        self.machine = machine
        self.parameters = {}

    @staticmethod
    def operator(key, operator, value):
        operator_map = {
            '==': '__eq__',
            '!=': '__ne__',
            '>': '__gt__',
            '<': '__lt__',
            '>=': '__ge__',
            '<=': '__le__'
        }
        if func := operator_map.get(operator):
            return getattr(key, func)(value)
        return False

    def int_compare(self):
        key, operator, value = self.value
        key_value = self.machine.get_parameter(key)
        if key_value is None:
            return False
        if not isinstance(value, int):
            value = int(value)
        return self.operator(key_value, operator, value)

    def float_compare(self):
        key, operator, value = self.value
        key_value = self.machine.get_parameter(key)
        if key_value is None:
            return False
        if not isinstance(value, float):
            value = float(value)
        return self.operator(key_value, operator, value)

    def duration_compare(self):
        assert isinstance(self.value, (int, float)), "时间必须为数字"
        if self.parameters.get('start_time') is None:
            self.parameters['start_time'] = datetime.now()
        current_time = datetime.now()
        final_time = self.parameters['start_time'] + timedelta(seconds=self.value)
        # timedelta转为datetime
        final_time = datetime.strptime(str(final_time), '%Y-%m-%d %H:%M:%S.%f')
        if current_time >= final_time:
            self.parameters['start_time'] = None
            self.parameters['left_time'] = None
            return True
        else:
            # 计算相差时间, 单位秒
            self.parameters['left_time'] = (final_time - current_time).total_seconds()
            self.machine.global_parameters['_left_time'] = self.parameters['left_time']
            return False

    def string_compare(self):
        key, operator, value = self.value
        key_value = self.machine.global_parameters.get(key, None)
        if key_value is None:
            return False
        return self.operator(key_value, operator, value)

    def bool_compare(self):
        key, value = self.value
        key_value = self.machine.get_parameter(key)
        if key_value is None:
            return False
        return key_value == value

    def __call__(self, *args, **kwargs):
        return getattr(self, self.type + '_compare')()
